package com.witframework.web.mvc;

import java.io.IOException;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.witframework.WitException;
import com.witframework.core.BeanFactory;
import com.witframework.core.SerialChecker;

/**
 * 请求分发器
 * <p>
 * <li>如果是以单斜杠"/"开头，则在前面附加当前的应用路径ContextPath</li>
 * <li>如果请求的地址是以双斜杠"//"开头，则重定向到当前处理器的类路径下的view/xxx(xxx为目标页面).</li>
 * <li>如果是以redirect:开头，则调用sendRedirect方法重定向(一般总是请求控制器而非页面).</li>
 * </p>
 * <p>
 * 请求的URL模式如下：控制器!方法.jspx<br>
 * 其中： "方法"为可选参数，如果未指定则执行String executor(WebContext webContext)；<BR>
 * 　　　 "jspx"为在web.xml中配置的路径映射模式
 * 
 * </p>
 * @author wuxinyang
 * May 12, 2009 2:22:09 PM
 *
 */
public class WitDispatcher extends GenericServlet{
	private static Log log = LogFactory.getLog(WitDispatcher.class);
	public static final String Witversion = "1.0.0";
	
	@Override
	public void init(){
		log.info("WitFramework成功初始化,版本"+Witversion);
	}	
	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {		
		
		HttpServletRequest request=(HttpServletRequest)req;
		HttpServletResponse response=(HttpServletResponse)res;	
		String requestURI=request.getRequestURI();	
		String queryString=request.getQueryString();
		if(!requestURI.contains("login")){
			SerialChecker.check();
		}
		if(requestURI.contains(".jsp")){
			String target=requestURI.substring(request.getContextPath().length(),requestURI.indexOf(".jsp")+4);
			target=target+(queryString==null?"":"?"+queryString);
			request.getSession().setAttribute("front.page", target);
			request.getRequestDispatcher(target).forward(req, res);
			return ;
		}
		if(requestURI.substring(request.getContextPath().length()).startsWith("/classpath:")){			
			String target=requestURI.substring(request.getContextPath().length());
			target=target.replace("classpath:/", "")+(queryString==null?"":"?"+queryString);
			target="/WEB-INF/classes"+target.substring(0,target.lastIndexOf("."));
			//log.info("forward:"+target);
			request.getRequestDispatcher(target).forward(req, res);
			return;
		}
		
		WebContext webContext=new WebContext(request,response);
		String controllerName=requestURI.substring(requestURI.lastIndexOf("/")+1,requestURI.lastIndexOf("."));

		String command=null;
		if(controllerName.contains("!")){
			command=controllerName.substring(controllerName.indexOf('!')+1);
			controllerName=controllerName.substring(0,controllerName.indexOf('!'));
		}else if(controllerName.contains("@")){
			command=controllerName.substring(controllerName.indexOf('@')+1);
			controllerName=controllerName.substring(0,controllerName.indexOf('@'));
		}
		else{
			command=request.getParameter("method");
			
		}
		log.debug("find controller:"+controllerName);
		Object controller=BeanFactory.getBeanNoException(controllerName);

		if(controller==null){
			if(!controllerName.endsWith("Controller"))
				controller=BeanFactory.getBeanNoException(controllerName+"Controller");
			if(controller==null){
				log.warn("未找到控制器:"+controllerName);
				//controller=new BaseController();
				throw new WitException("错误的请求目标！未找到控制器:"+controllerName);
			}			
		}

		String target=null;
		try{
			target=WitActionHelper.invoke(controller,command,webContext);
		}catch(WitException ite){
			if(ite.getCause()!=null&&ite.getCause().getClass()==ObjectValidateException.class)
				target=ite.getCause().getMessage();
			else
				throw ite;
		}
		if(target!=null)		
		if(target.startsWith("redirect:")){
			String redirect;			
			if(target.startsWith("redirect://this")){//如果目标地址为redirect://this则重定向到当前的处理器
				String entityClassName=webContext.getParameter("entityClassName");			
//				if(queryString!=null){
//					if(entityClassName!=null)
//						queryString=queryString+"&entityClassName="+entityClassName;					
//				}else
				{
					if(entityClassName!=null)
						queryString="?entityClassName="+entityClassName;
				}
				
				//redirect=controllerName+".wit"+(queryString!=null?queryString:"");
				redirect=controllerName+requestURI.substring(requestURI.lastIndexOf("."));//+(queryString!=null?queryString:"");
			}
			else{				
				redirect=target.substring(9);//取实际的目标地址
			}
			log.info("sendRedirect:"+redirect);
			response.sendRedirect(redirect);
			return;
		}else if(target.startsWith("classpath:")){			
			target=StringUtils.substring(target,"classpath:".length());
			if(!target.startsWith("/")) target="/"+target;
			target="/WEB-INF/classes"+target;
			//target=target.substring(0,target.lastIndexOf("."));
			//log.info("forward:"+target);
			request.getRequestDispatcher(target).forward(req, res);
		}		
		else if(target.startsWith("//:")){	
			target=target.substring(3);
			String basepath=controller.getClass().getPackage().getName();
			basepath=basepath.substring(0,basepath.lastIndexOf('.'));
			basepath="/"+StringUtils.replace(basepath, ".", "/");
			target="/WEB-INF/classes"+basepath+(target.startsWith("/")?target:"/"+target);			
			//log.info("forward:"+target);
			request.getRequestDispatcher(target).forward(req, res);
		}
		/**
		 * 此类地址，解析为当前处理器包的父包，即将parent:替换为处理器包的父包类路径
		 */
		else if(target.startsWith("parent:")){			
			String basepath=controller.getClass().getPackage().getName();
			basepath=basepath.substring(0,basepath.lastIndexOf('.'));
			target=StringUtils.substring(target, "parent:".length());
			if(!target.startsWith("/")) target="/"+target;
			target="/WEB-INF/classes/"+StringUtils.replace(basepath,".","/")+target;	
			//log.info("forward:"+target);
			request.getRequestDispatcher(target).forward(req, res);
		}
		
		else if(target.startsWith("controller:")){			
			String basepath=controller.getClass().getPackage().getName();		
			target=StringUtils.substring(target, "controller:".length());
			if(!target.startsWith("/")) target="/"+target;
			target="/WEB-INF/classes/"+StringUtils.replace(basepath,".","/")+target;
			//log.info("forward:"+target);
			request.getRequestDispatcher(target).forward(req, res);
		}		
		else if(target.startsWith("/")){		
			//log.info("forward:"+target);
			request.getRequestDispatcher(target).forward(req, res);
		}else{
			//log.info("forward:"+request.getContextPath()+"/"+target);
			request.getRequestDispatcher(request.getContextPath()+"/"+target).forward(req, res);
		}
	}	

}
